// Go作者版权所有。版权所有。
// 此源代码的使用受BSD样式的约束
// 可以在许可证文件中找到的许可证。

// +构建忽略

package main

import "strings"

// 笔记：
// -整数类型位于寄存器的低位。上部是垃圾。
// -布尔类型使用寄存器的低位字节。0=假，1=真。
// 上面的字节是垃圾。
// -在执行子寄存器操作时，我们尝试写入整个寄存器
// 避免部分寄存器写入的目标寄存器。
// -部分是未使用的部分
// 由延伸使用部分的标志填充。生长素的使用者
// 生长素未标记（如移位）必须小心。
// -SB“寄存器”使用指令相对寻址实现。这
// 对内存操作数的寻址时间和方式进行了一些限制
// 相对于SB可以使用：
// None
// 1.当发生错误时，伪指令并不总是映射到单个机器指令
// 使用SB“寄存器”来寻址数据。这是因为许多机器
// 指令没有相对长的（RL后缀）等价物。例如
// ADDload，组装为AG。
// None
// 2.使用相对寻址的加载和存储要求数据对齐
// 根据其大小（双字为8字节，字为4字节
// 等等）。
// None
// 我们可以通过插入LARL指令（加载地址）来解决这些问题
// 相对较长），但通常这会导致更糟糕的代码
// 生成，因为该地址无法重复使用。在中插入指令
// 汇编程序还意味着删除临时寄存器，这是一个长期目标
// 防止编译器执行此操作，以便可以将其作为普通
// 登记
// None
// 有关z/体系结构、指令集和
// 它所支持的寻址模式查看
// 操作：http:
// None
// 后缀对伪指令的位宽度进行编码。
// D（双字）=64位（经常省略）
// W（字）=32位
// H（半字）=16位
// B（字节）=8位
// S（单精度）=32位（省略双精度）

// 复制自.././s390x/reg.go
var regNamesS390X = []string{
	"R0",
	"R1",
	"R2",
	"R3",
	"R4",
	"R5",
	"R6",
	"R7",
	"R8",
	"R9",
	"R10",
	"R11",
	"R12",
	"g", // R13
	"R14",
	"SP", // R15
	"F0",
	"F1",
	"F2",
	"F3",
	"F4",
	"F5",
	"F6",
	"F7",
	"F8",
	"F9",
	"F10",
	"F11",
	"F12",
	"F13",
	"F14",
	"F15",

	// 如果添加寄存器，请在运行时更新asyncPreempt。

	// 伪寄存器
	"SB",
}

func init() {
	// 将reg名称映射到reg整数。
	if len(regNamesS390X) > 64 {
		panic("too many registers")
	}
	num := map[string]int{}
	for i, name := range regNamesS390X {
		num[name] = i
	}
	buildReg := func(s string) regMask {
		m := regMask(0)
		for _, r := range strings.Split(s, " ") {
			if n, ok := num[r]; ok {
				m |= regMask(1) << uint(n)
				continue
			}
			panic("register " + r + " not found")
		}
		return m
	}

	// 通用单个寄存器掩码
	var (
		sp  = buildReg("SP")
		sb  = buildReg("SB")
		r0  = buildReg("R0")
		tmp = buildReg("R11") // R11在少量指令中用作临时命令。

		// R10由汇编程序保留。
		gp   = buildReg("R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14")
		gpg  = gp | buildReg("g")
		gpsp = gp | sp

		// R0被认为在地址计算中包含值0。
		ptr     = gp &^ r0
		ptrsp   = ptr | sp
		ptrspsb = ptrsp | sb

		fp         = buildReg("F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15")
		callerSave = gp | fp | buildReg("g") // runtime.setg（以及任何调用它的东西）可能会重击g
		r1         = buildReg("R1")
		r2         = buildReg("R2")
		r3         = buildReg("R3")
	)
	// 寄存器掩码的公共片
	var (
		gponly = []regMask{gp}
		fponly = []regMask{fp}
	)

	// 公共区域信息
	var (
		gp01    = regInfo{inputs: []regMask{}, outputs: gponly}
		gp11    = regInfo{inputs: []regMask{gp}, outputs: gponly}
		gp11sp  = regInfo{inputs: []regMask{gpsp}, outputs: gponly}
		gp21    = regInfo{inputs: []regMask{gp, gp}, outputs: gponly}
		gp21sp  = regInfo{inputs: []regMask{gpsp, gp}, outputs: gponly}
		gp21tmp = regInfo{inputs: []regMask{gp &^ tmp, gp &^ tmp}, outputs: []regMask{gp &^ tmp}, clobbers: tmp}

		// 当用作要移位的位数时，R0计算为0
		// 所以我们需要从操作数中排除它。
		sh21 = regInfo{inputs: []regMask{gp, ptr}, outputs: gponly}

		addr    = regInfo{inputs: []regMask{sp | sb}, outputs: gponly}
		addridx = regInfo{inputs: []regMask{sp | sb, ptrsp}, outputs: gponly}

		gp2flags       = regInfo{inputs: []regMask{gpsp, gpsp}}
		gp1flags       = regInfo{inputs: []regMask{gpsp}}
		gp2flags1      = regInfo{inputs: []regMask{gp, gp}, outputs: gponly}
		gp11flags      = regInfo{inputs: []regMask{gp}, outputs: gponly}
		gp21flags      = regInfo{inputs: []regMask{gp, gp}, outputs: gponly}
		gp2flags1flags = regInfo{inputs: []regMask{gp, gp}, outputs: gponly}

		gpload       = regInfo{inputs: []regMask{ptrspsb, 0}, outputs: gponly}
		gploadidx    = regInfo{inputs: []regMask{ptrspsb, ptrsp, 0}, outputs: gponly}
		gpopload     = regInfo{inputs: []regMask{gp, ptrsp, 0}, outputs: gponly}
		gpstore      = regInfo{inputs: []regMask{ptrspsb, gpsp, 0}}
		gpstoreconst = regInfo{inputs: []regMask{ptrspsb, 0}}
		gpstoreidx   = regInfo{inputs: []regMask{ptrsp, ptrsp, gpsp, 0}}
		gpstorebr    = regInfo{inputs: []regMask{ptrsp, gpsp, 0}}
		gpstorelaa   = regInfo{inputs: []regMask{ptrspsb, gpsp, 0}, outputs: gponly}
		gpstorelab   = regInfo{inputs: []regMask{r1, gpsp, 0}, clobbers: r1}

		gpmvc = regInfo{inputs: []regMask{ptrsp, ptrsp, 0}}

		fp01        = regInfo{inputs: []regMask{}, outputs: fponly}
		fp21        = regInfo{inputs: []regMask{fp, fp}, outputs: fponly}
		fp31        = regInfo{inputs: []regMask{fp, fp, fp}, outputs: fponly}
		fp21clobber = regInfo{inputs: []regMask{fp, fp}, outputs: fponly}
		fpgp        = regInfo{inputs: fponly, outputs: gponly}
		gpfp        = regInfo{inputs: gponly, outputs: fponly}
		fp11        = regInfo{inputs: fponly, outputs: fponly}
		fp1flags    = regInfo{inputs: []regMask{fp}}
		fp11clobber = regInfo{inputs: fponly, outputs: fponly}
		fp2flags    = regInfo{inputs: []regMask{fp, fp}}

		fpload    = regInfo{inputs: []regMask{ptrspsb, 0}, outputs: fponly}
		fploadidx = regInfo{inputs: []regMask{ptrsp, ptrsp, 0}, outputs: fponly}

		fpstore    = regInfo{inputs: []regMask{ptrspsb, fp, 0}}
		fpstoreidx = regInfo{inputs: []regMask{ptrsp, ptrsp, fp, 0}}

		sync = regInfo{inputs: []regMask{0}}

		// LoweredAtomicCas可能会覆盖arg1，因此现在将其强制为R0。
		cas = regInfo{inputs: []regMask{ptrsp, r0, gpsp, 0}, outputs: []regMask{gp, 0}, clobbers: r0}

		// LoweredAtomicExchange在执行之前覆盖输出
		// CS{，G}，因此输出寄存器不能与
		// 输入寄存器。现在我们只需强制输出寄存器
		// R0。
		exchange = regInfo{inputs: []regMask{ptrsp, gpsp &^ r0, 0}, outputs: []regMask{r0, 0}}
	)

	var S390Xops = []opData{
		// 计划生育行动
		{name: "FADDS", argLength: 2, reg: fp21clobber, typ: "(Float32,Flags)", asm: "FADDS", commutative: true, resultInArg0: true}, // fp32 arg0+arg1
		{name: "FADD", argLength: 2, reg: fp21clobber, typ: "(Float64,Flags)", asm: "FADD", commutative: true, resultInArg0: true},   // fp64 arg0+arg1
		{name: "FSUBS", argLength: 2, reg: fp21clobber, typ: "(Float32,Flags)", asm: "FSUBS", resultInArg0: true},                    // fp32 arg0-arg1
		{name: "FSUB", argLength: 2, reg: fp21clobber, typ: "(Float64,Flags)", asm: "FSUB", resultInArg0: true},                      // fp64 arg0-arg1
		{name: "FMULS", argLength: 2, reg: fp21, asm: "FMULS", commutative: true, resultInArg0: true},                                // fp32 arg0*arg1
		{name: "FMUL", argLength: 2, reg: fp21, asm: "FMUL", commutative: true, resultInArg0: true},                                  // fp64 arg0*arg1
		{name: "FDIVS", argLength: 2, reg: fp21, asm: "FDIVS", resultInArg0: true},                                                   // fp32 arg0/arg1
		{name: "FDIV", argLength: 2, reg: fp21, asm: "FDIV", resultInArg0: true},                                                     // fp64 arg0/arg1
		{name: "FNEGS", argLength: 1, reg: fp11clobber, asm: "FNEGS", clobberFlags: true},                                            // fp32-arg0
		{name: "FNEG", argLength: 1, reg: fp11clobber, asm: "FNEG", clobberFlags: true},                                              // fp64-arg0
		{name: "FMADDS", argLength: 3, reg: fp31, asm: "FMADDS", resultInArg0: true},                                                 // fp32 arg1*arg2+arg0
		{name: "FMADD", argLength: 3, reg: fp31, asm: "FMADD", resultInArg0: true},                                                   // fp64 arg1*arg2+arg0
		{name: "FMSUBS", argLength: 3, reg: fp31, asm: "FMSUBS", resultInArg0: true},                                                 // fp32 arg1*arg2-arg0
		{name: "FMSUB", argLength: 3, reg: fp31, asm: "FMSUB", resultInArg0: true},                                                   // fp64 arg1*arg2-arg0
		{name: "LPDFR", argLength: 1, reg: fp11, asm: "LPDFR"},                                                                       // fp64/fp32设置符号位
		{name: "LNDFR", argLength: 1, reg: fp11, asm: "LNDFR"},                                                                       // fp64/fp32清除符号位
		{name: "CPSDR", argLength: 2, reg: fp21, asm: "CPSDR"},                                                                       // fp64/fp32将arg1符号位复制到arg0

		// 四舍五入为整数，仅浮点64。
		// None
		// 辅助舍入模式
		// ----+-----------------------------------
		// 1 |四舍五入至最近，系紧距离为0
		// 4 |四舍五入至最近，连至偶数
		// 5 |朝着0转
		// 6 |朝+∞
		// 7 |朝-∞
		{name: "FIDBR", argLength: 1, reg: fp11, asm: "FIDBR", aux: "Int8"},

		{name: "FMOVSload", argLength: 2, reg: fpload, asm: "FMOVS", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // fp32负载
		{name: "FMOVDload", argLength: 2, reg: fpload, asm: "FMOVD", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // fp64负载
		{name: "FMOVSconst", reg: fp01, asm: "FMOVS", aux: "Float32", rematerializeable: true},                               // fp32常数
		{name: "FMOVDconst", reg: fp01, asm: "FMOVD", aux: "Float64", rematerializeable: true},                               // fp64常数
		{name: "FMOVSloadidx", argLength: 3, reg: fploadidx, asm: "FMOVS", aux: "SymOff", symEffect: "Read"},                 // fp32负载由i索引
		{name: "FMOVDloadidx", argLength: 3, reg: fploadidx, asm: "FMOVD", aux: "SymOff", symEffect: "Read"},                 // fp64由i索引的加载

		{name: "FMOVSstore", argLength: 3, reg: fpstore, asm: "FMOVS", aux: "SymOff", faultOnNilArg0: true, symEffect: "Write"}, // fp32商店
		{name: "FMOVDstore", argLength: 3, reg: fpstore, asm: "FMOVD", aux: "SymOff", faultOnNilArg0: true, symEffect: "Write"}, // fp64存储
		{name: "FMOVSstoreidx", argLength: 4, reg: fpstoreidx, asm: "FMOVS", aux: "SymOff", symEffect: "Write"},                 // fp32由i存储索引
		{name: "FMOVDstoreidx", argLength: 4, reg: fpstoreidx, asm: "FMOVD", aux: "SymOff", symEffect: "Write"},                 // fp64由i存储索引

		// 二进制操作
		{name: "ADD", argLength: 2, reg: gp21sp, asm: "ADD", commutative: true, clobberFlags: true},                                                                  // arg0+arg1
		{name: "ADDW", argLength: 2, reg: gp21sp, asm: "ADDW", commutative: true, clobberFlags: true},                                                                // arg0+arg1
		{name: "ADDconst", argLength: 1, reg: gp11sp, asm: "ADD", aux: "Int32", typ: "UInt64", clobberFlags: true},                                                   // arg0+生长素
		{name: "ADDWconst", argLength: 1, reg: gp11sp, asm: "ADDW", aux: "Int32", clobberFlags: true},                                                                // arg0+生长素
		{name: "ADDload", argLength: 3, reg: gpopload, asm: "ADD", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"},   // arg0+*arg1。arg2=mem
		{name: "ADDWload", argLength: 3, reg: gpopload, asm: "ADDW", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0+*arg1。arg2=mem

		{name: "SUB", argLength: 2, reg: gp21, asm: "SUB", clobberFlags: true},                                                                                       // arg0-arg1
		{name: "SUBW", argLength: 2, reg: gp21, asm: "SUBW", clobberFlags: true},                                                                                     // arg0-arg1
		{name: "SUBconst", argLength: 1, reg: gp11, asm: "SUB", aux: "Int32", resultInArg0: true, clobberFlags: true},                                                // arg0-生长素
		{name: "SUBWconst", argLength: 1, reg: gp11, asm: "SUBW", aux: "Int32", resultInArg0: true, clobberFlags: true},                                              // arg0-生长素
		{name: "SUBload", argLength: 3, reg: gpopload, asm: "SUB", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"},   // arg0-*arg1。arg2=mem
		{name: "SUBWload", argLength: 3, reg: gpopload, asm: "SUBW", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0-*arg1。arg2=mem

		{name: "MULLD", argLength: 2, reg: gp21, asm: "MULLD", typ: "Int64", commutative: true, resultInArg0: true, clobberFlags: true},                                // arg0*arg1
		{name: "MULLW", argLength: 2, reg: gp21, asm: "MULLW", typ: "Int32", commutative: true, resultInArg0: true, clobberFlags: true},                                // arg0*arg1
		{name: "MULLDconst", argLength: 1, reg: gp11, asm: "MULLD", aux: "Int32", typ: "Int64", resultInArg0: true, clobberFlags: true},                                // arg0*生长素
		{name: "MULLWconst", argLength: 1, reg: gp11, asm: "MULLW", aux: "Int32", typ: "Int32", resultInArg0: true, clobberFlags: true},                                // arg0*生长素
		{name: "MULLDload", argLength: 3, reg: gpopload, asm: "MULLD", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0**arg1。arg2=mem
		{name: "MULLWload", argLength: 3, reg: gpopload, asm: "MULLW", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0**arg1。arg2=mem

		{name: "MULHD", argLength: 2, reg: gp21tmp, asm: "MULHD", typ: "Int64", commutative: true, resultInArg0: true, clobberFlags: true},   // （arg0*arg1）>>宽度
		{name: "MULHDU", argLength: 2, reg: gp21tmp, asm: "MULHDU", typ: "Int64", commutative: true, resultInArg0: true, clobberFlags: true}, // （arg0*arg1）>>宽度

		{name: "DIVD", argLength: 2, reg: gp21tmp, asm: "DIVD", resultInArg0: true, clobberFlags: true},   // arg0/arg1
		{name: "DIVW", argLength: 2, reg: gp21tmp, asm: "DIVW", resultInArg0: true, clobberFlags: true},   // arg0/arg1
		{name: "DIVDU", argLength: 2, reg: gp21tmp, asm: "DIVDU", resultInArg0: true, clobberFlags: true}, // arg0/arg1
		{name: "DIVWU", argLength: 2, reg: gp21tmp, asm: "DIVWU", resultInArg0: true, clobberFlags: true}, // arg0/arg1

		{name: "MODD", argLength: 2, reg: gp21tmp, asm: "MODD", resultInArg0: true, clobberFlags: true}, // arg0%arg1
		{name: "MODW", argLength: 2, reg: gp21tmp, asm: "MODW", resultInArg0: true, clobberFlags: true}, // arg0%arg1

		{name: "MODDU", argLength: 2, reg: gp21tmp, asm: "MODDU", resultInArg0: true, clobberFlags: true}, // arg0%arg1
		{name: "MODWU", argLength: 2, reg: gp21tmp, asm: "MODWU", resultInArg0: true, clobberFlags: true}, // arg0%arg1

		{name: "AND", argLength: 2, reg: gp21, asm: "AND", commutative: true, clobberFlags: true},                                                                    // arg0和arg1
		{name: "ANDW", argLength: 2, reg: gp21, asm: "ANDW", commutative: true, clobberFlags: true},                                                                  // arg0和arg1
		{name: "ANDconst", argLength: 1, reg: gp11, asm: "AND", aux: "Int64", resultInArg0: true, clobberFlags: true},                                                // arg0&生长素
		{name: "ANDWconst", argLength: 1, reg: gp11, asm: "ANDW", aux: "Int32", resultInArg0: true, clobberFlags: true},                                              // arg0&生长素
		{name: "ANDload", argLength: 3, reg: gpopload, asm: "AND", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"},   // arg0&*arg1。arg2=mem
		{name: "ANDWload", argLength: 3, reg: gpopload, asm: "ANDW", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0&*arg1。arg2=mem

		{name: "OR", argLength: 2, reg: gp21, asm: "OR", commutative: true, clobberFlags: true},                                                                    // arg0 | arg1
		{name: "ORW", argLength: 2, reg: gp21, asm: "ORW", commutative: true, clobberFlags: true},                                                                  // arg0 | arg1
		{name: "ORconst", argLength: 1, reg: gp11, asm: "OR", aux: "Int64", resultInArg0: true, clobberFlags: true},                                                // arg0 |生长素
		{name: "ORWconst", argLength: 1, reg: gp11, asm: "ORW", aux: "Int32", resultInArg0: true, clobberFlags: true},                                              // arg0 |生长素
		{name: "ORload", argLength: 3, reg: gpopload, asm: "OR", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"},   // arg0 |*arg1。arg2=mem
		{name: "ORWload", argLength: 3, reg: gpopload, asm: "ORW", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 |*arg1。arg2=mem

		{name: "XOR", argLength: 2, reg: gp21, asm: "XOR", commutative: true, clobberFlags: true},                                                                    // arg0^arg1
		{name: "XORW", argLength: 2, reg: gp21, asm: "XORW", commutative: true, clobberFlags: true},                                                                  // arg0^arg1
		{name: "XORconst", argLength: 1, reg: gp11, asm: "XOR", aux: "Int64", resultInArg0: true, clobberFlags: true},                                                // arg0^生长素
		{name: "XORWconst", argLength: 1, reg: gp11, asm: "XORW", aux: "Int32", resultInArg0: true, clobberFlags: true},                                              // arg0^生长素
		{name: "XORload", argLength: 3, reg: gpopload, asm: "XOR", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"},   // arg0^*arg1。arg2=mem
		{name: "XORWload", argLength: 3, reg: gpopload, asm: "XORW", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0^*arg1。arg2=mem

		// 带进位/借位链的算术运算。
		// None
		// 进位由条件代码2或3（GT或OV）表示。
		// 借用由条件代码0或1（EQ或LT）表示。
		{name: "ADDC", argLength: 2, reg: gp21flags, asm: "ADDC", typ: "(UInt64,Flags)", commutative: true},                          // （arg0+arg1，执行）
		{name: "ADDCconst", argLength: 1, reg: gp11flags, asm: "ADDC", typ: "(UInt64,Flags)", aux: "Int16"},                          // （arg0+生长素，执行）
		{name: "ADDE", argLength: 3, reg: gp2flags1flags, asm: "ADDE", typ: "(UInt64,Flags)", commutative: true, resultInArg0: true}, // （arg0+arg1+arg2（进位），进位）
		{name: "SUBC", argLength: 2, reg: gp21flags, asm: "SUBC", typ: "(UInt64,Flags)"},                                             // （arg0-arg1，借出）
		{name: "SUBE", argLength: 3, reg: gp2flags1flags, asm: "SUBE", typ: "(UInt64,Flags)", resultInArg0: true},                    // （arg0-arg1-arg2（借入），借出）

		// 比较。
		{name: "CMP", argLength: 2, reg: gp2flags, asm: "CMP", typ: "Flags"},   // arg0与arg1进行比较
		{name: "CMPW", argLength: 2, reg: gp2flags, asm: "CMPW", typ: "Flags"}, // arg0与arg1进行比较

		{name: "CMPU", argLength: 2, reg: gp2flags, asm: "CMPU", typ: "Flags"},   // arg0与arg1进行比较
		{name: "CMPWU", argLength: 2, reg: gp2flags, asm: "CMPWU", typ: "Flags"}, // arg0与arg1进行比较

		{name: "CMPconst", argLength: 1, reg: gp1flags, asm: "CMP", typ: "Flags", aux: "Int32"},     // arg0与生长素的比较
		{name: "CMPWconst", argLength: 1, reg: gp1flags, asm: "CMPW", typ: "Flags", aux: "Int32"},   // arg0与生长素的比较
		{name: "CMPUconst", argLength: 1, reg: gp1flags, asm: "CMPU", typ: "Flags", aux: "Int32"},   // arg0与生长素的比较
		{name: "CMPWUconst", argLength: 1, reg: gp1flags, asm: "CMPWU", typ: "Flags", aux: "Int32"}, // arg0与生长素的比较

		{name: "FCMPS", argLength: 2, reg: fp2flags, asm: "CEBR", typ: "Flags"},  // arg0与arg1、f32进行比较
		{name: "FCMP", argLength: 2, reg: fp2flags, asm: "FCMPU", typ: "Flags"},  // arg0与arg1比较，f64
		{name: "LTDBR", argLength: 1, reg: fp1flags, asm: "LTDBR", typ: "Flags"}, // arg0与0比较，f64
		{name: "LTEBR", argLength: 1, reg: fp1flags, asm: "LTEBR", typ: "Flags"}, // arg0与0比较，f32

		{name: "SLD", argLength: 2, reg: sh21, asm: "SLD"},                    // arg0<<arg1，移位量为mod 64
		{name: "SLW", argLength: 2, reg: sh21, asm: "SLW"},                    // arg0<<arg1，移位量为mod 64
		{name: "SLDconst", argLength: 1, reg: gp11, asm: "SLD", aux: "UInt8"}, // arg0<<生长素，移位量0-63
		{name: "SLWconst", argLength: 1, reg: gp11, asm: "SLW", aux: "UInt8"}, // arg0<<生长素，移位量0-31

		{name: "SRD", argLength: 2, reg: sh21, asm: "SRD"},                    // 未签名的arg0>>arg1，移位量为mod 64
		{name: "SRW", argLength: 2, reg: sh21, asm: "SRW"},                    // 无符号uint32（arg0）>>arg1，移位量为mod 64
		{name: "SRDconst", argLength: 1, reg: gp11, asm: "SRD", aux: "UInt8"}, // 无符号arg0>>生长素，移位量0-63
		{name: "SRWconst", argLength: 1, reg: gp11, asm: "SRW", aux: "UInt8"}, // 未签名的uint32（arg0）>>生长素，移位量0-31

		// 算术移位缓冲标志。
		{name: "SRAD", argLength: 2, reg: sh21, asm: "SRAD", clobberFlags: true},                    // 已签名的arg0>>arg1，移位量为mod 64
		{name: "SRAW", argLength: 2, reg: sh21, asm: "SRAW", clobberFlags: true},                    // 签名int32（arg0）>>arg1，移位量为mod 64
		{name: "SRADconst", argLength: 1, reg: gp11, asm: "SRAD", aux: "UInt8", clobberFlags: true}, // 署名arg0>>生长素，移位量0-63
		{name: "SRAWconst", argLength: 1, reg: gp11, asm: "SRAW", aux: "UInt8", clobberFlags: true}, // 署名int32（arg0）>>生长素，移位量0-31

		// 轮换指令。
		// 注意：无RLLGconst-请改用RISBGZ。
		{name: "RLLG", argLength: 2, reg: sh21, asm: "RLLG"},                  // arg0向左旋转arg1，旋转量0-63
		{name: "RLL", argLength: 2, reg: sh21, asm: "RLL"},                    // arg0向左旋转arg1，旋转量0-31
		{name: "RLLconst", argLength: 1, reg: gp11, asm: "RLL", aux: "UInt8"}, // arg0向左旋转生长素，旋转量0-31

		// 然后旋转（和|或|异或|插入）所选位指令。
		// None
		// Aux是一个s390x.RotateParams结构，包含开始、结束和旋转
		// 金额字段。
		// None
		// arg1向左旋转旋转量，然后从开始旋转位
		// 位到结束位（包括）使用逻辑
		// 指定的操作。位索引是从左到右指定的
		// MSB为0，LSB为63。
		// None
		// 示例：
		// |辅助|
		// |指令|开始|结束|金额| arg0 | arg1 |结果|
		// +-------------+-------+-----+--------+-----------------------+-----------------------+-----------------------+
		// |RXSBG（XOR）| 0 | 1 | 0 | 0xffff | ffff | 0xffff | ffff | 0x3fff | ffff | ffff ||
		// |RXSBG（XOR）| 62 | 63 | 0 | 0xffff | 0xffff | 0xffff | 0xffff | 0xffff | ffff | fffc|
		// |RXSBG（XOR）| 0 | 47 | 16 | 0xffff | 0x0000 | 0xffff | 0xffff | ffff | 0000 | ffff | 0xffff ||
		// +-------------+-------+-----+--------+-----------------------+-----------------------+-----------------------+
		// None
		{name: "RXSBG", argLength: 2, reg: gp21, asm: "RXSBG", resultInArg0: true, aux: "S390XRotateParams", clobberFlags: true}, // 旋转然后对所选位进行异或运算
		{name: "RISBGZ", argLength: 1, reg: gp11, asm: "RISBGZ", aux: "S390XRotateParams", clobberFlags: true},                   // 旋转然后插入选定位[归零]

		// 一元操作
		{name: "NEG", argLength: 1, reg: gp11, asm: "NEG", clobberFlags: true},   // -arg0
		{name: "NEGW", argLength: 1, reg: gp11, asm: "NEGW", clobberFlags: true}, // -arg0

		{name: "NOT", argLength: 1, reg: gp11, resultInArg0: true, clobberFlags: true},  // ^arg0
		{name: "NOTW", argLength: 1, reg: gp11, resultInArg0: true, clobberFlags: true}, // ^arg0

		{name: "FSQRT", argLength: 1, reg: fp11, asm: "FSQRT"},   // sqrt（arg0）
		{name: "FSQRTS", argLength: 1, reg: fp11, asm: "FSQRTS"}, // sqrt（arg0），浮动32

		// 条件寄存器移动。
		// 这些值的辅助值是表示条件代码掩码的s390x.CCMask值。
		{name: "LOCGR", argLength: 3, reg: gp2flags1, resultInArg0: true, asm: "LOCGR", aux: "S390XCCMask"}, // 如果arg2中的条件代码与aux中的屏蔽位匹配，则将arg1加载到arg0中。

		{name: "MOVBreg", argLength: 1, reg: gp11sp, asm: "MOVB", typ: "Int64"},    // 符号将arg0从int8扩展到int64
		{name: "MOVBZreg", argLength: 1, reg: gp11sp, asm: "MOVBZ", typ: "UInt64"}, // 零将arg0从int8扩展到int64
		{name: "MOVHreg", argLength: 1, reg: gp11sp, asm: "MOVH", typ: "Int64"},    // 符号将arg0从int16扩展到int64
		{name: "MOVHZreg", argLength: 1, reg: gp11sp, asm: "MOVHZ", typ: "UInt64"}, // 零将arg0从int16扩展到int64
		{name: "MOVWreg", argLength: 1, reg: gp11sp, asm: "MOVW", typ: "Int64"},    // 符号将arg0从int32扩展到int64
		{name: "MOVWZreg", argLength: 1, reg: gp11sp, asm: "MOVWZ", typ: "UInt64"}, // 零将arg0从int32扩展到int64

		{name: "MOVDconst", reg: gp01, asm: "MOVD", typ: "UInt64", aux: "Int64", rematerializeable: true}, // 生长素

		{name: "LDGR", argLength: 1, reg: gpfp, asm: "LDGR"}, // 将int64移动到float64（无转换）
		{name: "LGDR", argLength: 1, reg: fpgp, asm: "LGDR"}, // 将float64移动到int64（无转换）

		{name: "CFDBRA", argLength: 1, reg: fpgp, asm: "CFDBRA", clobberFlags: true}, // 将float64转换为int32
		{name: "CGDBRA", argLength: 1, reg: fpgp, asm: "CGDBRA", clobberFlags: true}, // 将float64转换为int64
		{name: "CFEBRA", argLength: 1, reg: fpgp, asm: "CFEBRA", clobberFlags: true}, // 将float32转换为int32
		{name: "CGEBRA", argLength: 1, reg: fpgp, asm: "CGEBRA", clobberFlags: true}, // 将float32转换为int64
		{name: "CEFBRA", argLength: 1, reg: gpfp, asm: "CEFBRA", clobberFlags: true}, // 将int32转换为float32
		{name: "CDFBRA", argLength: 1, reg: gpfp, asm: "CDFBRA", clobberFlags: true}, // 将int32转换为float64
		{name: "CEGBRA", argLength: 1, reg: gpfp, asm: "CEGBRA", clobberFlags: true}, // 将int64转换为float32
		{name: "CDGBRA", argLength: 1, reg: gpfp, asm: "CDGBRA", clobberFlags: true}, // 将int64转换为float64
		{name: "CLFEBR", argLength: 1, reg: fpgp, asm: "CLFEBR", clobberFlags: true}, // 将float32转换为uint32
		{name: "CLFDBR", argLength: 1, reg: fpgp, asm: "CLFDBR", clobberFlags: true}, // 将float64转换为uint32
		{name: "CLGEBR", argLength: 1, reg: fpgp, asm: "CLGEBR", clobberFlags: true}, // 将float32转换为uint64
		{name: "CLGDBR", argLength: 1, reg: fpgp, asm: "CLGDBR", clobberFlags: true}, // 将float64转换为uint64
		{name: "CELFBR", argLength: 1, reg: gpfp, asm: "CELFBR", clobberFlags: true}, // 将uint32转换为float32
		{name: "CDLFBR", argLength: 1, reg: gpfp, asm: "CDLFBR", clobberFlags: true}, // 将uint32转换为float64
		{name: "CELGBR", argLength: 1, reg: gpfp, asm: "CELGBR", clobberFlags: true}, // 将uint64转换为float32
		{name: "CDLGBR", argLength: 1, reg: gpfp, asm: "CDLGBR", clobberFlags: true}, // 将uint64转换为浮点64

		{name: "LEDBR", argLength: 1, reg: fp11, asm: "LEDBR"}, // 将float64转换为float32
		{name: "LDEBR", argLength: 1, reg: fp11, asm: "LDEBR"}, // 将float32转换为float64

		{name: "MOVDaddr", argLength: 1, reg: addr, aux: "SymOff", rematerializeable: true, symEffect: "Read"}, // arg0+生长素+辅助编码偏移量
		{name: "MOVDaddridx", argLength: 2, reg: addridx, aux: "SymOff", symEffect: "Read"},                    // arg0+arg1+auxint+aux

		// auxint+aux==将auxint和aux中符号的偏移量（如果有）添加到有效地址
		{name: "MOVBZload", argLength: 2, reg: gpload, asm: "MOVBZ", aux: "SymOff", typ: "UInt8", faultOnNilArg0: true, symEffect: "Read"},  // 从arg0+auxint+aux加载字节。arg1=mem。零延伸。
		{name: "MOVBload", argLength: 2, reg: gpload, asm: "MOVB", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"},                  // 同上，符号扩展到int64
		{name: "MOVHZload", argLength: 2, reg: gpload, asm: "MOVHZ", aux: "SymOff", typ: "UInt16", faultOnNilArg0: true, symEffect: "Read"}, // 从arg0+auxint+aux加载2个字节。arg1=mem。零延伸。
		{name: "MOVHload", argLength: 2, reg: gpload, asm: "MOVH", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"},                  // 同上，符号扩展到int64
		{name: "MOVWZload", argLength: 2, reg: gpload, asm: "MOVWZ", aux: "SymOff", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"}, // 从arg0+auxint+aux加载4个字节。arg1=mem。零延伸。
		{name: "MOVWload", argLength: 2, reg: gpload, asm: "MOVW", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"},                  // 同上，符号扩展到int64
		{name: "MOVDload", argLength: 2, reg: gpload, asm: "MOVD", aux: "SymOff", typ: "UInt64", faultOnNilArg0: true, symEffect: "Read"},   // 从arg0+auxint+aux加载8个字节。arg1=mem

		{name: "MOVWBR", argLength: 1, reg: gp11, asm: "MOVWBR"}, // arg0交换字节
		{name: "MOVDBR", argLength: 1, reg: gp11, asm: "MOVDBR"}, // arg0交换字节

		{name: "MOVHBRload", argLength: 2, reg: gpload, asm: "MOVHBR", aux: "SymOff", typ: "UInt16", faultOnNilArg0: true, symEffect: "Read"}, // 从arg0+auxint+aux加载2个字节。arg1=mem。反向字节。
		{name: "MOVWBRload", argLength: 2, reg: gpload, asm: "MOVWBR", aux: "SymOff", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"}, // 从arg0+auxint+aux加载4个字节。arg1=mem。反向字节。
		{name: "MOVDBRload", argLength: 2, reg: gpload, asm: "MOVDBR", aux: "SymOff", typ: "UInt64", faultOnNilArg0: true, symEffect: "Read"}, // 从arg0+auxint+aux加载8个字节。arg1=mem。反向字节。

		{name: "MOVBstore", argLength: 3, reg: gpstore, asm: "MOVB", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"},       // 将arg1中的字节存储到arg0+auxint+aux。arg2=mem
		{name: "MOVHstore", argLength: 3, reg: gpstore, asm: "MOVH", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"},       // 在arg1到arg0+auxint+aux中存储2个字节。arg2=mem
		{name: "MOVWstore", argLength: 3, reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"},       // 在arg1到arg0+auxint+aux中存储4个字节。arg2=mem
		{name: "MOVDstore", argLength: 3, reg: gpstore, asm: "MOVD", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"},       // 在arg1到arg0+auxint+aux中存储8个字节。arg2=mem
		{name: "MOVHBRstore", argLength: 3, reg: gpstorebr, asm: "MOVHBR", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 在arg1到arg0+auxint+aux中存储2个字节。arg2=mem。反向字节。
		{name: "MOVWBRstore", argLength: 3, reg: gpstorebr, asm: "MOVWBR", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 在arg1到arg0+auxint+aux中存储4个字节。arg2=mem。反向字节。
		{name: "MOVDBRstore", argLength: 3, reg: gpstorebr, asm: "MOVDBR", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 在arg1到arg0+auxint+aux中存储8个字节。arg2=mem。反向字节。

		{name: "MVC", argLength: 3, reg: gpmvc, asm: "MVC", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, faultOnNilArg1: true, symEffect: "None"}, // arg0=destptr，arg1=srcptr，arg2=mem，auxint=size，off

		// 索引加载/存储
		{name: "MOVBZloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVBZ", aux: "SymOff", typ: "UInt8", symEffect: "Read"},   // 从arg0+arg1+auxint+aux加载一个字节。arg2=mem。零延伸。
		{name: "MOVBloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVB", aux: "SymOff", typ: "Int8", symEffect: "Read"},      // 从arg0+arg1+auxint+aux加载一个字节。arg2=mem。标志延伸。
		{name: "MOVHZloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVHZ", aux: "SymOff", typ: "UInt16", symEffect: "Read"},  // 从arg0+arg1+auxint+aux加载2个字节。arg2=mem。零延伸。
		{name: "MOVHloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVH", aux: "SymOff", typ: "Int16", symEffect: "Read"},     // 从arg0+arg1+auxint+aux加载2个字节。arg2=mem。标志延伸。
		{name: "MOVWZloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVWZ", aux: "SymOff", typ: "UInt32", symEffect: "Read"},  // 从arg0+arg1+auxint+aux加载4个字节。arg2=mem。零延伸。
		{name: "MOVWloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVW", aux: "SymOff", typ: "Int32", symEffect: "Read"},     // 从arg0+arg1+auxint+aux加载4个字节。arg2=mem。标志延伸。
		{name: "MOVDloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVD", aux: "SymOff", typ: "UInt64", symEffect: "Read"},    // 从arg0+arg1+auxint+aux加载8个字节。arg2=mem
		{name: "MOVHBRloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVHBR", aux: "SymOff", typ: "Int16", symEffect: "Read"}, // 从arg0+arg1+auxint+aux加载2个字节。arg2=mem。反向字节。
		{name: "MOVWBRloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVWBR", aux: "SymOff", typ: "Int32", symEffect: "Read"}, // 从arg0+arg1+auxint+aux加载4个字节。arg2=mem。反向字节。
		{name: "MOVDBRloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVDBR", aux: "SymOff", typ: "Int64", symEffect: "Read"}, // 从arg0+arg1+auxint+aux加载8个字节。arg2=mem。反向字节。
		{name: "MOVBstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVB", aux: "SymOff", symEffect: "Write"},                // 将arg2中的字节存储到arg0+arg1+auxint+aux。arg3=mem
		{name: "MOVHstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVH", aux: "SymOff", symEffect: "Write"},                // 在arg2到arg0+arg1+auxint+aux中存储2个字节。arg3=mem
		{name: "MOVWstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVW", aux: "SymOff", symEffect: "Write"},                // 在arg2到arg0+arg1+auxint+aux中存储4个字节。arg3=mem
		{name: "MOVDstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVD", aux: "SymOff", symEffect: "Write"},                // 在arg2到arg0+arg1+auxint+aux中存储8个字节。arg3=mem
		{name: "MOVHBRstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVHBR", aux: "SymOff", symEffect: "Write"},            // 在arg2到arg0+arg1+auxint+aux中存储2个字节。arg3=mem。反向字节。
		{name: "MOVWBRstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVWBR", aux: "SymOff", symEffect: "Write"},            // 在arg2到arg0+arg1+auxint+aux中存储4个字节。arg3=mem。反向字节。
		{name: "MOVDBRstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVDBR", aux: "SymOff", symEffect: "Write"},            // 在arg2到arg0+arg1+auxint+aux中存储8个字节。arg3=mem。反向字节。

		// 对于storeconst ops，AuxInt字段对这两个字段进行编码
		// 要存储的值和存储的地址偏移量。
		// 将生长素浇铸到ValAndOff以提取Val和Off字段。
		{name: "MOVBstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVB", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 将ValAndOff（AuxInt）.Val（）的低位字节存储到arg0+ValAndOff（AuxInt）.Off（）+aux。arg1=mem
		{name: "MOVHstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVH", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 存储低2字节的。。。
		{name: "MOVWstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVW", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 存储低4字节的。。。
		{name: "MOVDstoreconst", argLength: 2, reg: gpstoreconst, asm: "MOVD", aux: "SymValAndOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // 存储8字节的。。。

		{name: "CLEAR", argLength: 2, reg: regInfo{inputs: []regMask{ptr, 0}}, asm: "CLEAR", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Write"},

		{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true},                                                // 调用静态函数aux。（*obj.LSym）。arg0=mem，auxint=argsize，返回mem
		{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{ptrsp, buildReg("R12"), 0}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true}, // 通过闭包调用函数。arg0=codeptr，arg1=closure，arg2=mem，auxint=argsize，返回mem
		{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{ptr}, clobbers: callerSave}, aux: "CallOff", clobberFlags: true, call: true},                         // 通过指针调用fn。arg0=codeptr，arg1=mem，auxint=argsize，返回mem

		// （反转标志（CMP a b））==（CMP b a）
		// InvertFlags是一个伪操作，不能出现在程序集输出中。
		{name: "InvertFlags", argLength: 1}, // arg0的反向

		// 伪操作
		{name: "LoweredGetG", argLength: 1, reg: gp01}, // arg0=mem
		// 调度器确保LoweredGetClosurePtr仅在入口块中发生，
		// 并将其排序到块的最开始，以防止其他
		// R12（闭包指针）的使用
		{name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{buildReg("R12")}}, zeroWidth: true},
		// arg0=ptr，arg1=mem，返回void。如果ptr为零，则出现故障。
		// LoweredGetCallerSP返回当前函数调用方的SP。
		{name: "LoweredGetCallerSP", reg: gp01, rematerializeable: true},
		// LoweredGetCallerPC计算其“调用者”将返回的PC。
		// 也就是说，如果f调用g“calls”getcallerpc，
		// 结果应为g将返回到的f内的PC。
		// 有关更详细的讨论，请参阅runtime/stubs.go。
		{name: "LoweredGetCallerPC", reg: gp01, rematerializeable: true},
		{name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{ptrsp}}, clobberFlags: true, nilCheck: true, faultOnNilArg0: true},
		// 取整运算以阻止融合的乘加提取。
		{name: "LoweredRound32F", argLength: 1, reg: fp11, resultInArg0: true, zeroWidth: true},
		{name: "LoweredRound64F", argLength: 1, reg: fp11, resultInArg0: true, zeroWidth: true},

		// LoweredWB调用runtime.gcWriteBarrier。arg0=destptr，arg1=srcptr，arg2=mem，aux=runtime.gcWriteBarrier
		// 如有必要，它会保存所有GP寄存器，
		// 但击倒R14（LR），因为这是一个电话。
		{name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("R2"), buildReg("R3")}, clobbers: (callerSave &^ gpg) | buildReg("R14")}, clobberFlags: true, aux: "Sym", symEffect: "None"},

		// 这些函数有三个，因此它们可以有三个不同的寄存器输入。
		// 当我们检查0<=c<=cap（A），然后检查0<=b<=c（b），然后检查0<=A<=b（c），我们需要
		// 要匹配的默认寄存器，因此我们不需要不必要地复制寄存器。
		{name: "LoweredPanicBoundsA", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r2, r3}}, typ: "Mem", call: true}, // arg0=idx，arg1=len，arg2=mem，返回内存。AuxInt包含报告代码（参见generic.go中的PanicBounds）。
		{name: "LoweredPanicBoundsB", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r1, r2}}, typ: "Mem", call: true}, // arg0=idx，arg1=len，arg2=mem，返回内存。AuxInt包含报告代码（参见generic.go中的PanicBounds）。
		{name: "LoweredPanicBoundsC", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r0, r1}}, typ: "Mem", call: true}, // arg0=idx，arg1=len，arg2=mem，返回内存。AuxInt包含报告代码（参见generic.go中的PanicBounds）。

		// 恒定条件代码值。条件代码可以是0、1、2或3。
		{name: "FlagEQ"}, // CC=0（相等）
		{name: "FlagLT"}, // CC=1（小于）
		{name: "FlagGT"}, // CC=2（大于）
		{name: "FlagOV"}, // CC=3（溢出）

		// 快速BCR序列化以确保存储加载顺序。
		{name: "SYNC", argLength: 1, reg: sync, asm: "SYNC", typ: "Mem"},

		// 原子负荷。这些只是正常加载，但返回<value，memory>元组
		// 因此，它们可以与其他负载一起正确订购。
		// 从arg0+auxint+aux加载。arg1=mem。
		{name: "MOVBZatomicload", argLength: 2, reg: gpload, asm: "MOVBZ", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"},
		{name: "MOVWZatomicload", argLength: 2, reg: gpload, asm: "MOVWZ", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"},
		{name: "MOVDatomicload", argLength: 2, reg: gpload, asm: "MOVD", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"},

		// 原子仓库。这些只是普通商店。
		// 将arg1存储到arg0+auxint+aux。arg2=mem。
		{name: "MOVBatomicstore", argLength: 3, reg: gpstore, asm: "MOVB", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "Write"},
		{name: "MOVWatomicstore", argLength: 3, reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "Write"},
		{name: "MOVDatomicstore", argLength: 3, reg: gpstore, asm: "MOVD", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "Write"},

		// 原子补充道。
		// *（arg0+auxint+aux）+=arg1。arg2=mem。
		// 返回<old contents of*（arg0+auxint+aux），memory>的元组。
		{name: "LAA", argLength: 3, reg: gpstorelaa, asm: "LAA", typ: "(UInt32,Mem)", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "RdWr"},
		{name: "LAAG", argLength: 3, reg: gpstorelaa, asm: "LAAG", typ: "(UInt64,Mem)", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "RdWr"},
		{name: "AddTupleFirst32", argLength: 2}, // arg1=元组<x，y>。返回<x+arg0，y>。
		{name: "AddTupleFirst64", argLength: 2}, // arg1=元组<x，y>。返回<x+arg0，y>。

		// 原子位运算。
		// 注意：“floor”操作将指针向下舍入到最近的单词边界
		// 这反映了它们在运行时的使用方式。
		{name: "LAN", argLength: 3, reg: gpstore, asm: "LAN", typ: "Mem", clobberFlags: true, hasSideEffects: true},         // *arg0&=arg1。arg2=mem。
		{name: "LANfloor", argLength: 3, reg: gpstorelab, asm: "LAN", typ: "Mem", clobberFlags: true, hasSideEffects: true}, // *（楼层（arg0，4））&=arg1。arg2=mem。
		{name: "LAO", argLength: 3, reg: gpstore, asm: "LAO", typ: "Mem", clobberFlags: true, hasSideEffects: true},         // *arg0 |=arg1。arg2=mem。
		{name: "LAOfloor", argLength: 3, reg: gpstorelab, asm: "LAO", typ: "Mem", clobberFlags: true, hasSideEffects: true}, // *（楼层（arg0，4））|=arg1。arg2=mem。

		// 比较和交换。
		// arg0=指针，arg1=旧值，arg2=新值，arg3=内存。
		// 如果*（arg0+auxint+aux）==arg1{
		// *（arg0+auxint+aux）=arg2
		// 返回（真，内存）
		// }否则{
		// 返回（假，内存）
		// }
		// 请注意，这些指令还返回arg1中的旧值，但我们忽略它。
		// TODO:用这些返回标志代替布尔。当前系统生成：
		// 反恐精英。。。
		// MOVD$0，ret
		// BNE 2（个人电脑）
		// MOVD$1，ret
		// CMPW ret，$0
		// B。。。
		// 而不仅仅是
		// 反恐精英。。。
		// 北京。。。
		// 但我们不能这样做，因为使用ops的内存还不能生成标志
		// （flagalloc希望移动生成标志的指令）。
		{name: "LoweredAtomicCas32", argLength: 4, reg: cas, asm: "CS", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "RdWr"},
		{name: "LoweredAtomicCas64", argLength: 4, reg: cas, asm: "CSG", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "RdWr"},

		// 降低了原子交换，使用比较和交换进行模拟。
		// 将arg1存储到arg0+auxint+aux，arg2=mem。
		{name: "LoweredAtomicExchange32", argLength: 3, reg: exchange, asm: "CS", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "RdWr"},
		{name: "LoweredAtomicExchange64", argLength: 3, reg: exchange, asm: "CSG", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, symEffect: "RdWr"},

		// 找到最左边的一个
		{
			name:         "FLOGR",
			argLength:    1,
			reg:          regInfo{inputs: gponly, outputs: []regMask{buildReg("R0")}, clobbers: buildReg("R1")},
			asm:          "FLOGR",
			typ:          "UInt64",
			clobberFlags: true,
		},

		// 人口计数
		// None
		// 统计arg0每个字节中的1个数
		// 并将结果放入相应的字节中
		// 结果如何。
		{
			name:         "POPCNT",
			argLength:    1,
			reg:          gp11,
			asm:          "POPCNT",
			typ:          "UInt64",
			clobberFlags: true,
		},

		// 无符号乘法（64x64）→ 128)
		// None
		// 将两个64位输入操作数相乘，并将128位结果放入
		// 奇偶寄存器对。目标对中的第二个寄存器也包含
		// 输入操作数之一。因为我们目前没有办法指定
		// 偶数-奇数寄存器对我们将该寄存器对硬编码为R2:R3。
		{
			name:      "MLGR",
			argLength: 2,
			reg:       regInfo{inputs: []regMask{gp, r3}, outputs: []regMask{r2, r3}},
			asm:       "MLGR",
		},

		// 对POPCNT指令的输出求和的伪操作
		{name: "SumBytes2", argLength: 1, typ: "UInt8"}, // 对arg0中最右边的2个字节求和，忽略溢出
		{name: "SumBytes4", argLength: 1, typ: "UInt8"}, // 对arg0中最右边的4个字节求和，忽略溢出
		{name: "SumBytes8", argLength: 1, typ: "UInt8"}, // 对arg0中的所有字节求和，忽略溢出

		// 存储多个
		{
			name:           "STMG2",
			argLength:      4,
			reg:            regInfo{inputs: []regMask{ptrsp, buildReg("R1"), buildReg("R2"), 0}},
			aux:            "SymOff",
			typ:            "Mem",
			asm:            "STMG",
			faultOnNilArg0: true,
			symEffect:      "Write",
			clobberFlags:   true, // TODO（mundaym）：当前使用AGFI处理大偏移
		},
		{
			name:           "STMG3",
			argLength:      5,
			reg:            regInfo{inputs: []regMask{ptrsp, buildReg("R1"), buildReg("R2"), buildReg("R3"), 0}},
			aux:            "SymOff",
			typ:            "Mem",
			asm:            "STMG",
			faultOnNilArg0: true,
			symEffect:      "Write",
			clobberFlags:   true, // TODO（mundaym）：当前使用AGFI处理大偏移
		},
		{
			name:      "STMG4",
			argLength: 6,
			reg: regInfo{inputs: []regMask{
				ptrsp,
				buildReg("R1"),
				buildReg("R2"),
				buildReg("R3"),
				buildReg("R4"),
				0,
			}},
			aux:            "SymOff",
			typ:            "Mem",
			asm:            "STMG",
			faultOnNilArg0: true,
			symEffect:      "Write",
			clobberFlags:   true, // TODO（mundaym）：当前使用AGFI处理大偏移
		},
		{
			name:           "STM2",
			argLength:      4,
			reg:            regInfo{inputs: []regMask{ptrsp, buildReg("R1"), buildReg("R2"), 0}},
			aux:            "SymOff",
			typ:            "Mem",
			asm:            "STMY",
			faultOnNilArg0: true,
			symEffect:      "Write",
			clobberFlags:   true, // TODO（mundaym）：当前使用AGFI处理大偏移
		},
		{
			name:           "STM3",
			argLength:      5,
			reg:            regInfo{inputs: []regMask{ptrsp, buildReg("R1"), buildReg("R2"), buildReg("R3"), 0}},
			aux:            "SymOff",
			typ:            "Mem",
			asm:            "STMY",
			faultOnNilArg0: true,
			symEffect:      "Write",
			clobberFlags:   true, // TODO（mundaym）：当前使用AGFI处理大偏移
		},
		{
			name:      "STM4",
			argLength: 6,
			reg: regInfo{inputs: []regMask{
				ptrsp,
				buildReg("R1"),
				buildReg("R2"),
				buildReg("R3"),
				buildReg("R4"),
				0,
			}},
			aux:            "SymOff",
			typ:            "Mem",
			asm:            "STMY",
			faultOnNilArg0: true,
			symEffect:      "Write",
			clobberFlags:   true, // TODO（mundaym）：当前使用AGFI处理大偏移
		},

		// 大动作
		// auxint=循环后的剩余字节（rem）
		// arg0=dst内存地址（在R1中，作为副作用更改）
		// arg1=src内存地址（在R2中，作为副作用更改）
		// arg2=指向要在循环中移动的最后一个地址的指针+256
		// arg3=mem
		// 返回mem
		// None
		// mvc:mvc$256，0（R2），0（R1）
		// 动产$256（R1），R1
		// 动产$256（R2），R2
		// CMP R2，Rarg2
		// BNE-mvc
		// MVC$rem，0（R2），0（R1）
		{
			name:      "LoweredMove",
			aux:       "Int64",
			argLength: 4,
			reg: regInfo{
				inputs:   []regMask{buildReg("R1"), buildReg("R2"), gpsp},
				clobbers: buildReg("R1 R2"),
			},
			clobberFlags:   true,
			typ:            "Mem",
			faultOnNilArg0: true,
			faultOnNilArg1: true,
		},

		// 大清
		// auxint=循环后的剩余字节（rem）
		// arg0=dst内存地址（在R1中，作为副作用更改）
		// arg1=指向循环+256中最后一个零地址的指针
		// arg2=mem
		// 返回mem
		// None
		// 清除：清除$256，0（R1）
		// 动产$256（R1），R1
		// CMP R1，Rarg2
		// 不清楚
		// 清除$rem，0（R1）
		{
			name:      "LoweredZero",
			aux:       "Int64",
			argLength: 3,
			reg: regInfo{
				inputs:   []regMask{buildReg("R1"), gpsp},
				clobbers: buildReg("R1"),
			},
			clobberFlags:   true,
			typ:            "Mem",
			faultOnNilArg0: true,
		},
	}

	// s390x上的所有块都将其条件代码掩码（s390x.CCMask）作为辅助值。
	// 条件代码掩码是一个4位掩码，其中每个位对应一个条件
	// 代码值。如果条件代码的值与条件中设置的位匹配
	// 然后执行第一个后续代码。否则，第二个继任者将被解雇
	// 执行。
	// None
	// |条件代码值|掩码位|
	// +----------------------+------------+
	// |0（相等）| 0b1000（8）|
	// |1（小于）| 0b0100（4）|
	// |2（大于）| 0b0010（2）|
	// |3（无序）| 0b0001（1）|
	// None
	// 注意：比较和分支指令不得设置位3（0b0001）。
	var S390Xblocks = []blockData{
		// 有条件的分支
		{name: "BRC", controls: 1, aux: "S390XCCMask"}, // 条件代码值（标志）为控件[0]

		// 比较和分支（寄存器）
		// -集成控件[0]与控件[1]的比较
		// -两个控制值必须在通用寄存器中
		{name: "CRJ", controls: 2, aux: "S390XCCMask"},   // 有符号32位整数比较
		{name: "CGRJ", controls: 2, aux: "S390XCCMask"},  // 有符号64位整数比较
		{name: "CLRJ", controls: 2, aux: "S390XCCMask"},  // 无符号32位整数比较
		{name: "CLGRJ", controls: 2, aux: "S390XCCMask"}, // 无符号64位整数比较

		// 比较和分支（立即注册）
		// -将对照[0]与生长素进行比较
		// -控制值必须在通用寄存器中
		// -生长素值是符号扩展的，用于符号比较
		// 和零扩展用于无符号比较
		{name: "CIJ", controls: 1, aux: "S390XCCMaskInt8"},    // 有符号32位整数比较
		{name: "CGIJ", controls: 1, aux: "S390XCCMaskInt8"},   // 有符号64位整数比较
		{name: "CLIJ", controls: 1, aux: "S390XCCMaskUint8"},  // 无符号32位整数比较
		{name: "CLGIJ", controls: 1, aux: "S390XCCMaskUint8"}, // 无符号64位整数比较
	}

	archs = append(archs, arch{
		name:            "S390X",
		pkg:             "cmd/internal/obj/s390x",
		genfile:         "../../s390x/ssa.go",
		ops:             S390Xops,
		blocks:          S390Xblocks,
		regnames:        regNamesS390X,
		gpregmask:       gp,
		fpregmask:       fp,
		framepointerreg: -1, // 不用
		linkreg:         int8(num["R14"]),
		imports: []string{
			"cmd/internal/obj/s390x",
		},
	})
}
